#!/usr/bin/env python3
import socket
import time
'''
执行流程：
遍历WiFi信息, 循环发布每个字节内容。
5个帧为一组, 每组发送wifi信息的一个字节。

核心设计：
由于网络加密，发布的数据包内容不可见，因此采用数据包长度来传达信息。
发布数字1, 调用send_frame, 1+偏置值255, 数据包长为256
发送字符'1', 调用send_ascii_string, '1'对应ASCII 49 + 偏置值255, 数据包长为304

帧类型定义：
​1. ​起始帧​​
功能：标识数据流开始
构造：send_frame(127) → 负载长度=127+255=382字节
2. ​​消息长度帧​​
功能：声明总字符数
示例：send_frame(len("HUAWEI...")) → 长度值编码
​3. ​索引帧​​
功能：标记当前字符位置
范围：0 ≤ index < 消息长度
​​4. 字符数据帧​​
功能：传输ASCII字符
构造：send_ascii_string(ch) → 长度=ASCII码+255 
​​5. 结束帧​​
功能：标识数据流结束
构造：send_frame(128) → 负载长度=128+255=383字节
'''

# 常量定义
BROADCAST_IP = "255.255.255.255"  # 广播 IP 地址，用于 UDP 广播
PORT = 7001  # UDP 目标端口号
INTERVAL = 0.01  # 发送间隔（秒），10ms，控制发送频率
MESSAGE = "HUAWEI-7EGBK8_HiLink:1231231230"  # 要发送的消息内容

# 创建 UDP 套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # AF_INET 表示 IPv4，SOCK_DGRAM 表示 UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)  # 启用广播选项，允许发送到广播地址

def send_frame(input):
    """
    发送单个 UDP 数据帧，负载长度基于输入值加 255。
    
    参数:
        input: 输入值，可以是整数（0-255）或单字符字符串。
    
    返回:
        bool: 发送成功返回 True，失败返回 False。
    """
    try:
        # 类型判断与转换逻辑
        if isinstance(input, int):
            # 如果输入是整数，确保在 0-255 范围内
            if not 0 <= input <= 255:
                return False  # 超出范围直接返回
            length = input + 255  # 计算负载长度：输入值 + 255
        else:
            # 如果输入是字符串（单字符），转换为 ASCII 码并加 255
            length = ord(input) + 255

        # 数据包构造与发送
        data = bytes([0xFF] * length)  # 创建负载，全部填充 0xFF，长度为 length
        sock.sendto(data, (BROADCAST_IP, PORT))  # 发送 UDP 数据包到广播地址和端口
        print(f"Sent {len(data)} bytes (原始输入: {repr(input)}) to {BROADCAST_IP}:{PORT}")
        time.sleep(INTERVAL)
        return True
        
    except Exception as e:
        print(f"发送异常: {str(e)}")  # 打印异常信息
        return False

def send_ascii_string(ch):
    """
    发送单字符的 UDP 数据帧，负载长度基于字符的 ASCII 码加 255。
    
    参数:
        ch: 单字符字符串。
    """
    length = ord(ch) + 255  # 计算负载长度：字符 ASCII 码 + 255
    data = bytes([0xFF] * length)  # 创建负载，全部填充 0xFF
    sock.sendto(data, (BROADCAST_IP, PORT))  # 发送 UDP 数据包
    print(f"Sent {len(data)} bytes for '{ch}' to {BROADCAST_IP}:{PORT}")
    time.sleep(INTERVAL)

try:
    # 主循环，持续发送消息
    while True:
        # 遍历消息中的每个字符
        for i in range(len(MESSAGE)):
            # 发送协议定义的帧序列
            send_frame(127)  # 发送起始帧（负载长度 127 + 255 = 382 字节）
            send_frame(len(MESSAGE))  # 发送消息长度帧（表示字符总数）
            send_frame(i)  # 发送当前字符的索引
            send_ascii_string(MESSAGE[i])  # 发送当前字符的 ASCII 数据帧
            send_frame(128)  # 发送结束帧（负载长度 128 + 255 = 383 字节）
            print('-' * 80)  # 打印分隔线，便于调试输出
except KeyboardInterrupt:
    print("\nStopped.")  # 用户按 Ctrl+C 停止程序
finally:
    sock.close()  # 确保关闭套接字，释放资源